﻿using CommonUtil;
using CommonUtil.EmguHelp;
using CommonUtil.Model;
using DataAccess;
using DirectShowLib;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using FaceDetection;
using log4net;
using Microsoft.ProjectOxford.Face;
using Microsoft.ProjectOxford.Face.Contract;
using Microsoft.ProjectOxford.Face.Controls;
using ServiceHelpers;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using view.ComControl;
using view.Model;

namespace view
{
    public partial class MainFrm : Form
    {
        #region 画面私有属性
        /// <summary>
        /// 日志对象
        /// </summary>
        private ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        /// <summary>
        /// 摄像头对象
        /// </summary>
        private VideoCapture _capture = null;
        private Mat _frame;
        private Mat _flipFrame;
        //private Mat _grayFrame;
        //private Mat _smallGrayFrame;
        //private Mat _smoothedGrayFrame;
        //private Mat _cannyFrame;

        /// <summary>
        /// EmguCV人脸识别共通类
        /// </summary>
        private FaceDetectUtil faceDetect;
        /// <summary>
        /// Faces to identify
        /// </summary>
        private ObservableCollection<FaceInfo> _faces = new ObservableCollection<FaceInfo>();
        /// <summary>
        /// Person database
        /// </summary>
        private ObservableCollection<Person> _persons = new ObservableCollection<Person>();
        /// <summary>
        /// 人脸组是否存在
        /// </summary>
        private bool groupExists = false;
        /// <summary>
        /// 是否正在自动人脸识别
        /// </summary>
        private bool bolIsIdentifying = false;
        /// <summary>
        /// App配置信息
        /// </summary>
        private AppConfigInfo appInfo;
        /// <summary>
        /// 语言播报对象
        /// </summary>
        private SpeechHelper speech;

        //public ObservableCollection<FaceInfo> TargetFaces
        //{
        //    get
        //    {
        //        return _faces;
        //    }
        //}

        public int MaxImageSize
        {
            get
            {
                return 640;
            }
        }
        #endregion

        #region 画面事件
        /// <summary>
        /// 画面构造方法
        /// </summary>
        public MainFrm()
        {
            log.Debug("构造方法初期化开始");
            InitializeComponent();

            // 获得配置信息
            appInfo = ConfigManager.getConfigInfo();

            speech = new SpeechHelper();

            log.Debug("构造方法初期化结束");
        }

        /// <summary>
        /// 画面初期化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainFrm_Load(object sender, EventArgs e)
        {
            log.Debug("MainFrm 画面初期化开始");
            btnOpenCam.Enabled = false;
            DsDevice[] _SystemCamereas = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);

            for (int i = 0; i < _SystemCamereas.Length; i++)
            {
                cmbCameraSelection.Items.Add(_SystemCamereas[i].Name);
            }
            if (cmbCameraSelection.Items.Count > 0)
            {
                cmbCameraSelection.SelectedIndex = 0;
                btnOpenCam.Enabled = true; //Enable the start
            }

            // 判定默认人脸组是否存在
            isPersonGroupExists();

            // 人脸对象控件非表示
            pictureBox1.Visible = false;
            // 自动人脸识别停止
            timMarkFace.Stop();
            timeCountdown.Stop();

            speech.SpeakAsync("欢迎使用人脸识别系统");

            log.Debug("MainFrm 画面初期化结束");
        }

        /// <summary>
        /// 人员管理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmiPerson_Click(object sender, System.EventArgs e)
        {
            log.Debug("人员管理 开始");
            PersonFrm childForm = new PersonFrm();
            childForm.Show();
            log.Debug("人员管理 结束");
        }

        /// <summary>
        /// 开启关闭摄像头
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpenCam_Click(object sender, System.EventArgs e)
        {
            log.Debug("MainFrm btnOpenCam_Click 开始");
            ReleaseData();
            CvInvoke.UseOpenCL = false;

            try
            {
                _frame = new Mat();
                _flipFrame = new Mat();
                //_grayFrame = new Mat();
                //_smallGrayFrame = new Mat();
                //_smoothedGrayFrame = new Mat();
                //_cannyFrame = new Mat();

                _capture = new VideoCapture(cmbCameraSelection.SelectedIndex);
                // 获取帧
                _capture.ImageGrabbed += ProcessFrame;
                _capture.Start();

            }
            catch (NullReferenceException excpt)
            {
                log.Error(excpt);
                MessageBox.Show(excpt.Message);
            }

            if (_capture != null)
            {
                if (!_capture.IsOpened)
                {
                    MessageBox.Show("无法打开摄像头");
                }
                else
                {
                    btnOpenCam.Text = "刷新";
                    btnCloseCam.Enabled = true;

                    // 训练人脸库
                    isTrainPersonGroup();
                }
            }
            log.Debug("MainFrm btnOpenCam_Click 结束");
        }

        /// <summary>
        /// 关闭摄像头
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCloseCam_Click(object sender, EventArgs e)
        {
            log.Debug("开始");

            // 自动人脸识别停止
            timMarkFace.Stop();
            // 取消
            _capture.ImageGrabbed -= ProcessFrame;
            // 摄像头停止
            _capture.Stop();
            // 摄像头图片销毁
            captureImageBox.Image = null;
            // 强制刷新
            captureImageBox.Refresh();
            btnOpenCam.Text = "打开";

            // 拍照识别
            btnPhotograph.Enabled = false;
            btnSelectFile.Enabled = false;
            // 自动抓拍
            cheAutoPhotograph.Enabled = false;
            cheAutoPhotograph.Checked = false;
            // 人脸识别
            chkFaceIdentify.Enabled = false;
            chkFaceIdentify.Checked = false;
            // 情感识别
            chkDetectEmotion.Enabled = false;
            chkDetectEmotion.Checked = false;

            log.Debug("结束");
        }

        /// <summary>
        /// 拍照识别人脸信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnPhotograph_Click(object sender, EventArgs e)
        {
            log.Debug("MainFrm btnPhotograph_Click 开始");

            if (_capture == null || captureImageBox.Image == null || !_capture.IsOpened)
            {
                MessageBox.Show("摄像头没有打开！");
            }
            else
            {
                // 判断是否正在识别中
                if (bolIsIdentifying == false)
                {
                    // 设置正在识别中
                    bolIsIdentifying = true;
                    var faceImageName = ImageUtil.getNewFileName();
                    //_capture.QueryFrame().Bitmap.Save(faceImageName);
                    //captureImageBox.Image.Save(faceImageName);//保存图片
                    //captureImageBox.Image.Save(faceImageName);
                    _flipFrame.Save(faceImageName);

                    pictureBox1.Visible = true;
                    pictureBox1.Image = Image.FromFile(faceImageName);

                    // 调用微软认知服务人脸识别
                    faceIdentify(faceImageName, chkFaceIdentify.Checked, chkDetectEmotion.Checked);

                    bolIsIdentifying = false;
                }
            }
            log.Debug("MainFrm btnPhotograph_Click 结束");
        }

        /// <summary>
        /// 选择图片进行识别
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSelectFile_Click(object sender, EventArgs e)
        {
            log.Debug("选择图片进行识别 开始");

            // 判断是否正在识别中
            if (bolIsIdentifying == false)
            {
                // 设置正在识别中
                bolIsIdentifying = true;

                //显示选择文件对话框 
                OpenFileDialog openFileDialog1 = new OpenFileDialog();
                openFileDialog1.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF";
                openFileDialog1.FilterIndex = 2;
                openFileDialog1.RestoreDirectory = true;

                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    pictureBox1.Visible = true;
                    pictureBox1.Image = Image.FromFile(openFileDialog1.FileName);
                    faceIdentify(openFileDialog1.FileName, chkFaceIdentify.Checked, chkDetectEmotion.Checked);
                }
                bolIsIdentifying = false;
            }
            log.Debug("选择图片进行识别 结束");
        }

        /// <summary>
        /// 自动抓拍事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cheAutoPhotograph_Changed(object sender, EventArgs e)
        {
            if (_capture == null || captureImageBox.Image == null || !_capture.IsOpened)
            {
                cheAutoPhotograph.Checked = false;
                MessageBox.Show("摄像头没有打开！");
            }
            else
            {
                // 自动识别间隔时间
                var time = int.Parse(appInfo.IdentifyTime);
                timMarkFace.Interval = time * 1000;

                // 自拍间隔时间
                txtCountdownTime.Text = appInfo.IdentifyTime;

                if (cheAutoPhotograph.Checked)
                {
                    timeCountdown.Start();
                    // 自动人脸识别开始
                    timMarkFace.Start();
                    timeCountdown.Start();
                }
                else
                {
                    timeCountdown.Stop();
                    // 自动人脸识别停止
                    timMarkFace.Stop();
                    timeCountdown.Stop();
                }
            }
        }

        /// <summary>
        /// 自动更新倒计时状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timeCountdown_Tick(object sender, EventArgs e)
        {
            var countdownTime = txtCountdownTime.Text;
            var tmpTime = (int.Parse(countdownTime) - 1);
            txtCountdownTime.Text = tmpTime == 0 ? appInfo.IdentifyTime: tmpTime.ToString();
        }

        /// <summary>
        /// 自动人脸设别定时器（100毫秒）
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timMarkFace_Tick(object sender, EventArgs e)
        {
            try
            {
                if (!cheAutoPhotograph.Checked)
                {
                    timMarkFace.Stop();
                    timeCountdown.Stop();
                }
                else
                {
                    #region 微软人脸识别方法
                    //if (bolIsIdentifying == false)
                    //{
                    //    bolIsIdentifying = true;
                    //    //保存图片
                    //    string path = System.Environment.CurrentDirectory + @"\tmp";
                    //    if (!Directory.Exists(path))
                    //    {
                    //        Directory.CreateDirectory(path);
                    //    }
                    //    faceImageName = path + @"\" + Guid.NewGuid().ToString() + ".jpg";
                    //    captureImageBox.Image.Save(faceImageName);

                    //    //// 识别人脸画头像框
                    //    //faceRectangle(faceImageName);
                    //    // 识别人脸画头像框和查询人脸信息
                    //    faceIdentify(faceImageName);
                    //}
                    #endregion

                    #region Emgu.CV人脸识别方法
                    // 判断是否正在识别中
                    if (bolIsIdentifying == false)
                    {
                        // 设置正在识别中
                        bolIsIdentifying = true;

                        statuslabel.Text = "开始查找人脸信息";
                        if (faceDetect == null)
                        {
                            faceDetect = new FaceDetectUtil();
                        }

                        // 图片翻转设置（默认0：无，1：水平，2：垂直）
                        //CvInvoke.Flip(_frame, _frame, FlipType.Horizontal);
                        var queryFrame = _flipFrame;
                        //var queryFrame = _capture.QueryFrame();
                        var fdo = faceDetect.faceRecognize(queryFrame);
                        if (fdo.facesRectangle.Count > 0)
                        {
                            statuslabel.Text = String.Format("找到{0}个人脸信息", fdo.facesRectangle.Count);

                            statuslabel.Text += ",正在识别中";

                            // 取消自动抓拍
                            //cheAutoPhotograph.Checked = false;

                            //captureImageBox.Image.Save(faceImageName);

                            pictureBox1.Visible = true;
                            pictureBox1.Image = queryFrame.Bitmap;

                            //保存图片
                            var faceImageName = ImageUtil.getNewFileName();
                            pictureBox1.Image.Save(faceImageName);

                            // 调用微软认知服务人脸识别
                            faceIdentify(faceImageName, chkFaceIdentify.Checked, chkDetectEmotion.Checked);
                            // 拍照识别
                            //faceIdentify(faceImageName);
                            
                            statuslabel.Text += ",识别完成";

                            // 识别完成之后，删除图片文件
                            //File.Delete(faceImageName);
                        }

                        //// 识别出人脸之后显示画框的图片
                        //captureImageBox.Image = fdo.originalImg.ToImage<Bgr, Byte>();
                        //// 强制刷新
                        //captureImageBox.Refresh();

                        // 摄像头停止工作
                        //_capture.Stop();
                        else
                        {
                            statuslabel.Text = "没找到人脸信息";
                        }
                        // 设置识别完成
                        bolIsIdentifying = false;
                    }
                    #endregion

                    //captureImageBox.Image = faceDetect.faceRecognize(_capture.QueryFrame()).originalImg.ToImage<Bgr, Byte>();
                    //captureImageBox.Refresh();

                    //// 
                    //pictureBox1.Image = faceDetect.faceRecognize(_capture.QueryFrame()).originalImg.Bitmap;
                    //// 强制刷新
                    //pictureBox1.Refresh();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        /// <summary>
        /// 环境设定
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void menuSetting_Click(object sender, EventArgs e)
        {
            SettingFrm setting = new SettingFrm();
            setting.ShowDialog();

            // 获得配置信息
            appInfo = ConfigManager.getConfigInfo();
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 训练人脸库
        /// </summary>
        private async void isTrainPersonGroup()
        {
            try
            {
                // Start train person group
                //MainWindow.Log("Request: Training group \"{0}\"", GroupName);
                await FaceServiceHelper.faceClient.TrainPersonGroupAsync(appInfo.FaceGroupName);

                // Wait until train completed
                while (true)
                {
                    await Task.Delay(1000);
                    var status = await FaceServiceHelper.faceClient.GetPersonGroupTrainingStatusAsync(appInfo.FaceGroupName);
                    //MainWindow.Log("Response: {0}. Group \"{1}\" training process is {2}", "Success", GroupName, status.Status);
                    if (status.Status != Status.Running)
                    {
                        break;
                    }
                }
                // 拍照识别
                btnPhotograph.Enabled = true;
                btnSelectFile.Enabled = true;
                // 自动抓拍
                cheAutoPhotograph.Enabled = true;
                // 人脸识别
                chkFaceIdentify.Enabled = true;
                // 情感识别
                chkDetectEmotion.Enabled = true;
            }
            catch (FaceAPIException ex)
            {
                log.Error(ex);
                //MainWindow.Log("Response: {0}. {1}", ex.ErrorCode, ex.ErrorMessage);
            }
        }
        /// <summary>
        /// 获取摄像头帧
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="arg"></param>
        private void ProcessFrame(object sender, EventArgs arg)
        {
            if (_capture != null && _capture.Ptr != IntPtr.Zero)
            {
                // 接收数据 对该帧进行解码
                _capture.Retrieve(_frame, 0);

                var frameSize = _frame.Size;

                // 图片翻转设置（默认0：无，1：水平，2：垂直）
                CvInvoke.Flip(_frame, _flipFrame, FlipType.Horizontal);

                // 设定为摄像头控件的大小
                CvInvoke.Resize(_flipFrame, _flipFrame, captureImageBox.Size, 0, 0, Inter.Linear);

                // 把正常图片转化为黑白色彩
                //CvInvoke.CvtColor(_frame, _grayFrame, ColorConversion.Bgr2Gray);

                //CvInvoke.PyrDown(_grayFrame, _smallGrayFrame);

                //CvInvoke.PyrUp(_smallGrayFrame, _smoothedGrayFrame);

                //CvInvoke.Canny(_smoothedGrayFrame, _cannyFrame, 100, 60);

                if (appInfo.Facetracking)
                {
                    if (faceDetect == null)
                    {
                        faceDetect = new FaceDetectUtil();
                    }
                    var fdo = faceDetect.faceRecognize(_flipFrame);
                    if (fdo.facesRectangle.Count > 0)
                    {
                        // 识别出人脸之后显示画框的图片
                        captureImageBox.Image = fdo.originalImg.ToImage<Bgr, Byte>();
                    }
                    else
                    {
                        captureImageBox.Image = _flipFrame;
                    }
                }
                else
                {
                    captureImageBox.Image = _flipFrame;
                }
            }
        }

        public void CaptureProcess(object sender, EventArgs arg)
        {
            var frame = _capture.QueryFrame();

            if (frame != null)
            {
                long detectionTime;
                List<Rectangle> faces = new List<Rectangle>();
                List<Rectangle> eyes = new List<Rectangle>();

                DetectFace.Detect(
                  frame, "App_Config/haarcascade_frontalface_default.xml", "App_Config/haarcascade_eye.xml",
                  faces, eyes,
                  out detectionTime);
                if (faces.Count > 0)
                {
                    foreach (Rectangle face in faces)
                        CvInvoke.Rectangle(frame, face, new Bgr(Color.Red).MCvScalar, 2);
                    foreach (Rectangle eye in eyes)
                        CvInvoke.Rectangle(frame, eye, new Bgr(Color.Blue).MCvScalar, 2);

                    pictureBox1.Image = frame.Bitmap;
                    pictureBox1.Visible = false;
                }


                //face detection   

                /*frame = frame.Flip(Emgu.CV.CvEnum.FLIP.HORIZONTAL);  
                smallframe = frame.Resize(1 / scale, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);//缩放摄像头拍到的大尺寸照片  
                gray = smallframe.Convert<Gray, Byte>(); //Convert it to Grayscale  
                gray._EqualizeHist();//均衡化  

                CascadeClassifier ccr = new CascadeClassifier(haarXmlPath);
                Rectangle[] rects = ccr.DetectMultiScale(gray, 1.3, 3, new Size(20, 20), Size.Empty);
                foreach (Rectangle r in rects)
                {
                    //This will focus in on the face from the haar results its not perfect but it will remove a majoriy  
                    //of the background noise  
                    Rectangle facesDetected = r;
                    facesDetected.X += (int)(facesDetected.Height * 0.6);
                    facesDetected.Y += (int)(facesDetected.Width * 0.8);
                    facesDetected.Height += (int)(facesDetected.Height * 0.1);
                    facesDetected.Width += (int)(facesDetected.Width * 0.2);

                    frame.Draw(facesDetected, new Bgr(Color.Red), 3);//绘制检测框  
                }


                imageBox_capture.Image = frame;*/
            }
        }

        /// <summary>
        /// 销毁摄像头对象
        /// </summary>
        private void ReleaseData()
        {
            cheAutoPhotograph.Checked = false;
            if (_capture != null)
                _capture.Dispose();
        }

        private void faceDetection(string imgName)
        {
            IImage image = new UMat(imgName, ImreadModes.Color);

            long detectionTime;
            List<Rectangle> faces = new List<Rectangle>();
            List<Rectangle> eyes = new List<Rectangle>();

            DetectFace.Detect(
            image, "haarcascade_frontalface_default.xml", "haarcascade_eye.xml",
            faces, eyes,
            out detectionTime);

            foreach (Rectangle face in faces)
                CvInvoke.Rectangle(image, face, new Bgr(Color.Red).MCvScalar, 2);

            pictureBox1.Image = image.Bitmap;

            // ProgressBarFrm.Run();

            faceIdentify(imgName);

        }

        /// <summary>
        /// 调用微软认知服务人脸识别
        /// </summary>
        /// <param name="fileName">认知服务的图片文件名</param>
        /// <param name="isFaceIdentify">是否进行人脸识别</param>
        /// <param name="isDetectEmotion">是否进行情感识别</param>
        private async void faceIdentify(string fileName, bool isFaceIdentify = false, bool isDetectEmotion = false)
        {
            log.Info(String.Format("人脸认知服务开始 {0}", fileName));
            statuslabel.Text = String.Format("人脸认知服务开始 {0}", fileName);
            this.pnlResult.Controls.Clear();
            // 获得用于渲染的图片信息
            var imageInfo = UIHelper.GetImageInfoForRendering(fileName);

            // 读取图片文件
            using (Stream fileStream = File.OpenRead(fileName))
            {
                try
                {
                    // 读取人脸
                    var faces = await FaceServiceHelper.faceClient.DetectAsync(fileStream, true, true, new FaceAttributeType[] { FaceAttributeType.Gender, FaceAttributeType.Age, FaceAttributeType.Smile, FaceAttributeType.Glasses, FaceAttributeType.HeadPose, FaceAttributeType.FacialHair, FaceAttributeType.Emotion });

                    log.Info(String.Format("读取到的人脸数:{0}", faces.Length));

                    IImage image = new UMat(fileName, ImreadModes.Color);

                    int faceIdx = 0;
                    // 将检测结果转换为UI绑定对象进行渲染
                    foreach (var face in UIHelper.CalculateFaceRectangleForRendering(faces, imageInfo))
                    {
                        //TargetFaces.Add(face);

                        log.Info(String.Format("{0} 人脸ID:{1}", faceIdx, face.FaceId));

                        // 画出人脸框
                        CvInvoke.Rectangle(image, new Rectangle(face.Left, face.Top, face.Width, face.Height), new Bgr(Color.Red).MCvScalar, 2);
                        
                        // 人员信息控件
                        FaceResultCtl faceCtl = new FaceResultCtl();
                        faceCtl.Location = new Point(5, faceIdx * faceCtl.Height);
                        this.pnlResult.Controls.Add(faceCtl);

                        // 裁剪人脸图片
                        var faceFilename = ImageUtil.KiCut(fileName, new Rectangle(face.Left, face.Top, face.Width, face.Height));
                        face.FaceImgname = faceFilename;

                        // 是否设置人脸识别信息
                        if (isFaceIdentify)
                        {
                            log.Info(String.Format("{0} 通过人脸组名称取得头像:{1}", faceIdx, face.FaceId));
                            // 通过人脸组名称取得头像
                            Person[] Persons = await FaceServiceHelper.faceClient.GetPersonsAsync(appInfo.FaceGroupName);

                            log.Info(String.Format("{0} 根据取得的人脸ID到指定的人脸组中查询人脸的信息:{1}", faceIdx, face.FaceId));
                            // 根据取得的人脸ID到指定的人脸组中查询人脸的信息
                            var identifyResult = await FaceServiceHelper.faceClient.IdentifyAsync(appInfo.FaceGroupName, faces.Select(ff => ff.FaceId).ToArray());
                            var res = identifyResult[faceIdx];
                            if (res.Candidates.Length > 0 && Persons.Any(p => p.PersonId.ToString().Equals(res.Candidates[0].PersonId.ToString())))
                            {
                                // 人名
                                face.PersonName = Persons.Where(p => p.PersonId.ToString().Equals(res.Candidates[0].PersonId.ToString())).First().Name;
                                // 人ID
                                face.PersonId = res.Candidates[0].PersonId.ToString();

                                log.Info(String.Format("{0} 本地人脸信息:{1}", faceIdx, face.FaceId));
                                // 本地人脸信息
                                faceCtl.EmployeeInfo = setLocalFaceInfo(face.PersonId);
                            }
                            else
                            {
                                // 人名
                                face.PersonName = "未知";

                                // 添加照片至人脸组
                                //TaskAsyncHelper.RunAsync(AddPersonFaceToFaceGroup(faceFilename), null);
                                //AddPersonFaceToFaceGroup(faceFilename);
                                await Task.Run(() => AddPersonFaceToFaceGroup(faceFilename));
                            }
                        }

                        // 微软识别信息
                        faceCtl.FaceInfo = face;

                        // 是否设置情感识别信息
                        if (isDetectEmotion)
                        {
                            faceCtl.EmotionScores = face.EmotionScores;
                        }

                        faceIdx++;
                    }
                    //if (faceIdx > 0)
                    //{
                    //    // 自动抓拍取消
                    //    cheAutoPhotograph.Checked = false;
                    //}
                    pictureBox1.Image = image.Bitmap;

                    if (appInfo.SpeechEnabled)
                    {
                        log.Info(String.Format("开始播报人脸信息:{0}", fileName));
                        // 播报人脸信息
                        isSpeekFaceInfo();
                    }
                    //if (faces.Length > 0 && groupExists)
                    //{
                    //}
                    //else
                    //{
                    //    // 设置识别完成
                    //    bolIsIdentifying = false;
                    //}
                }
                catch (FaceAPIException ex)
                {
                    // 自动人脸识别停止
                    timMarkFace.Stop();
                    bolIsIdentifying = false;
                }
            }

            statuslabel.Text += ",人脸认知服务结束";
            log.Info(String.Format("人脸认知服务结束 {0}", fileName));
            // 删除图片文件
            //File.Delete(fileName);
        }

        /// <summary>
        /// 添加照片至人脸组
        /// </summary>
        /// <param name="imgPath">人脸图片</param>
        private async void AddPersonFaceToFaceGroup(string imgPath)
        {
            // 创建新的人ID
            string personName = Guid.NewGuid().ToString();
            var personId = (await FaceServiceHelper.faceClient.CreatePersonAsync(appInfo.FaceGroupName, personName)).PersonId.ToString();
            log.Info(String.Format("添加照片到人脸组{0}", imgPath));

            using (var fStream = File.OpenRead(imgPath))
            {
                try
                {
                    // Update person faces on server side
                    var persistFace = await FaceServiceHelper.faceClient.AddPersonFaceAsync(appInfo.FaceGroupName, Guid.Parse(personId), fStream, imgPath);
                    //return new Tuple<string, ClientContract.AddPersistedFaceResult>(imgPath, persistFace);
                    log.Info(String.Format("添加照片到人脸组 识别完成 {0}", imgPath));
                }
                catch (FaceAPIException ex)
                {
                    log.Error(ex);
                    // if operation conflict, retry.
                    if (ex.ErrorCode.Equals("ConcurrentOperationConflict"))
                    {
                        //imageList.Add(imgPath);
                        //return null;
                    }
                    // if operation cause rate limit exceed, retry.
                    else if (ex.ErrorCode.Equals("RateLimitExceeded"))
                    {
                        //imageList.Add(imgPath);
                        //return null;
                    }
                    else if (ex.ErrorMessage.Contains("more than 1 face in the image."))
                    {
                        log.Error("添加人脸至人脸组的时候，只能有一张人脸！");
                        //Interlocked.Increment(ref invalidImageCount);
                    }
                    // Here we simply ignore all detection failure in this sample
                    // You may handle these exceptions by check the Error.Error.Code and Error.Message property for ClientException object
                    //return new Tuple<string, ClientContract.AddPersistedFaceResult>(imgPath, null);
                }
            }
        }

        /// <summary>
        /// 设置人员显示信息
        /// </summary>
        /// <param name="Persons"></param>
        /// <param name="identifyResult"></param>
        /// <param name="iIdentCnt"></param>
        /// <param name="idx"></param>
        private void setPersonInfo(Person[] Persons, IdentifyResult[] identifyResult, int iIdentCnt, int idx)
        {
            var outString = new StringBuilder();
            // 人员信息控件
            FaceResultCtl faceCtl = new FaceResultCtl();
            faceCtl.Location = new Point(5, 10 + idx * faceCtl.Height);
            this.pnlResult.Controls.Add(faceCtl);

            //var face = TargetFaces[idx];
            //var res = identifyResult[idx];
            //if (res.Candidates.Length > 0 && Persons.Any(p => p.PersonId.ToString().Equals(res.Candidates[0].PersonId.ToString())))
            //{
            //    face.PersonName = Persons.Where(p => p.PersonId.ToString().Equals(res.Candidates[0].PersonId.ToString())).First().Name;
            //    face.PersonId = res.Candidates[0].PersonId.ToString();
            //    outString.AppendFormat(iIdentCnt + ". Azure识别：人员ID {0}", face.FaceId);
            //    outString.AppendFormat("\n Azure：年龄【{0}】, 性别【{1}】, 眼睛【{2}】, 面部毛发【{3}】, 情感【{4}】, 头部姿势【{5}】"
            //           , face.Age, face.Gender, face.Glasses, face.FacialHair, face.Emotion, face.HeadPose);
            //}
            //else
            //{
            //    face.PersonName = "未知";
            //    outString.AppendFormat(iIdentCnt + ". Azure识别：人员ID {0} ", face.FaceId);
            //    outString.AppendFormat("\n Azure：年龄【{0}】, 性别【{1}】, 眼睛【{2}】, 面部毛发【{3}】, 情感【{4}】, 头部姿势【{5}】"
            //           , face.Age, face.Gender, face.Glasses, face.FacialHair, face.Emotion, face.HeadPose);
            //    outString.AppendFormat("\n 本地：姓名【{0}】\n", face.PersonName);
            //}

            speech.SpeakAsync("你好，" + outString);
            log.Info(outString);

            // 微软识别信息
            //faceCtl.FaceInfo = face;
            // 查找数据库 获取本地信息
            //faceCtl.EmployeeInfo = setLocalFaceInfo(face.PersonId);
        }

        /// <summary>
        /// 查询本地人脸信息
        /// </summary>
        /// <param name="personId">人员ID</param>
        private EmployeeInfo setLocalFaceInfo(string personId)
        {
            var employeeInfo = new EmployeeInfo();
            var selectSql = "SELECT ID, GroupId, Personid, Name, Birthday , SexMale, Mobile, Email, DeptName, Position , Nationality, Hobby FROM Person ";
            var selectWhereSql = " WHERE GroupId='" + appInfo.FaceGroupName + "' AND Personid = '" + personId + "'";
            var personInfo = MySqlCommonHelper.GetDataSet(MySqlCommonHelper.Conn, CommandType.Text, selectSql + selectWhereSql, null).Tables[0].DefaultView;
            if (personInfo.Table.Rows.Count > 0)
            {
                var itemRow = personInfo.Table.Rows[0];
                // 用户ID
                //tmpFace.EmployeeId = itemRow["ID"].ToString();
                // 姓名
                employeeInfo.Name = itemRow["Name"].ToString();
                // 性别
                employeeInfo.Gender = itemRow["SexMale"].ToString();
                // 电话
                employeeInfo.Mobile = itemRow["Mobile"].ToString();
                // Email
                employeeInfo.Email = itemRow["Email"].ToString();
                // 部门
                employeeInfo.DeptName = itemRow["DeptName"].ToString();
                // 职务
                employeeInfo.Position = itemRow["Position"].ToString();
                // 生日
                employeeInfo.Birthday = itemRow["Birthday"].ToString();
                // 国籍
                employeeInfo.Nationality = itemRow["Nationality"].ToString();
                // 爱好
                employeeInfo.Hobby = itemRow["Hobby"].ToString();
                employeeInfo.Remark = "";

            }
            log.Info("查询本地人脸信息");
            return employeeInfo;
        }

        private async void faceRectangle(string fileName)
        {
            var imageInfo = UIHelper.GetImageInfoForRendering(fileName);

            using (var fileStream = File.OpenRead(fileName))
            {
                try
                {
                    // 读取人脸
                    var faces = await FaceServiceHelper.faceClient.DetectAsync(fileStream, true, true, new FaceAttributeType[] { FaceAttributeType.Gender, FaceAttributeType.Age, FaceAttributeType.Smile, FaceAttributeType.Glasses, FaceAttributeType.HeadPose, FaceAttributeType.FacialHair, FaceAttributeType.Emotion });

                    IImage image = new UMat(fileName, ImreadModes.Color);

                    // 将检测结果转换为UI绑定对象进行渲染
                    foreach (var face in UIHelper.CalculateFaceRectangleForRendering(faces, imageInfo))
                    {
                        //TargetFaces.Add(face);
                        CvInvoke.Rectangle(image, new Rectangle(face.Left, face.Top, face.Width, face.Height), new Bgr(Color.Red).MCvScalar, 2);
                    }
                    pictureBox1.Visible = true;
                    pictureBox1.Image = image.Bitmap;
                }
                catch (FaceAPIException ex)
                {
                    //MessageBox.Show(ex.ErrorMessage, "error", MessageBoxButtons.OK);
                }
                finally
                {
                    bolIsIdentifying = false;
                }
            }
            File.Delete(fileName);
        }

        /// <summary>
        /// 判定人脸组是否存在
        /// </summary>
        private async void isPersonGroupExists()
        {
            try
            {
                //MainWindow.Log("Request: Group {0} will be used to build a person database. Checking whether the group exists.", GroupName);

                await FaceServiceHelper.faceClient.GetPersonGroupAsync(appInfo.FaceGroupName);
                groupExists = true;
                //MainWindow.Log("Response: Group {0} exists.", GroupName);
            }
            catch (FaceAPIException ex)
            {

            }

            #region 如果人脸组存在的话，弹出确认框是否要删除
            if (groupExists)
            {
                if (false)
                {
                    // 如果人脸组存在的话，弹出确认框是否要删除
                    var cleanGroup = MessageBox.Show(string.Format("在创建新人数据库之前，需要对组“{0}”进行清理。单击“确定”进行，组“{0}”将被清除。", appInfo.FaceGroupName), "Warning", MessageBoxButtons.OKCancel);
                    if (cleanGroup == DialogResult.OK)
                    {
                        await FaceServiceHelper.faceClient.DeletePersonGroupAsync(appInfo.FaceGroupName);
                    }
                    else
                    {
                        return;
                    }
                }
            }
            else
            {
                // 人脸组不存在的时候，新建人脸组
                try
                {
                    await FaceServiceHelper.faceClient.CreatePersonGroupAsync(appInfo.FaceGroupName, appInfo.FaceGroupName);
                    //MainWindow.Log("Response: Success. Group \"{0}\" created", GroupName);
                }
                catch (FaceAPIException ex)
                {
                    //MainWindow.Log("Response: {0}. {1}", ex.ErrorCode, ex.ErrorMessage);
                    return;
                }
            }
            #endregion

        }

        /// <summary>
        /// 播报人脸信息
        /// </summary>
        private void isSpeekFaceInfo()
        {
            var outString = new StringBuilder();

            var faces = this.pnlResult.Controls;
            foreach (var item in faces)
            {
                var tmpFace = ((FaceResultCtl)(item));
                if (!string.Empty.Equals(tmpFace.SpeekInfo))
                {
                    outString.Append(tmpFace.SpeekInfo).Append(",");
                }
            }
            if (string.Empty.Equals(outString.ToString()))
            {
                log.Info("亲，您确认您开启了人脸识别了吗？");
                //SpeechHelper.SpeakAsync("おめでとうございます");
                speech.SpeakAsync("亲，您确认您开启了人脸识别了吗？");
            }
            else
            {
                log.Info("你好，" + outString.ToString());
                speech.SpeakAsync("你好，" + outString.ToString());
            }
        }

        #endregion

    }
}
